using UnityEngine;
using System.Collections;

public class player : MonoBehaviour {
	public Movement move;
	public Transform character;
	public GameObject cursorPrefab;
	
	// Settings
	public float cameraSmoothing = 0.01f;
	public float cameraPreview = 2.0f;
	
	// Cursor settings
	public float cursorPlaneHeight = 0;
	public float cursorFacingCamera = 0;
	public float cursorSmallerWithDistance = 0;
	public float cursorSmallerWhenClose = 1;
	
	// Private memeber data
	private Camera mainCamera;
	
	private Transform cursorObject;
	
	private Transform mainCameraTransform;
	private Vector3 cameraVelocity = Vector3.zero;
	private Vector3 cameraOffset = Vector3.zero;
	private Vector3 initOffsetToPlayer;
	
	// Prepare a cursor point varibale. This is the mouse position on PC and controlled by the thumbstick on mobiles.
	private Vector3 cursorScreenPosition;
	
	private Plane playerMovementPlane;
	
	private Quaternion screenMovementSpace;
	private Vector3 screenMovementForward;
	private Vector3 screenMovementRight;
	
	void Awake() {
		move.movementDirection = Vector2.zero;
		move.facingDirection = Vector2.zero;
		
		// Set main camera
		mainCamera = Camera.main;
		mainCameraTransform = mainCamera.transform;
		
		// Ensure we have character set
		// Default to using the transform this component is on
		if (!character)
			character = transform;
		
		initOffsetToPlayer = mainCameraTransform.position - character.position;
		
		if (cursorPrefab) {
			cursorObject = (Instantiate (cursorPrefab) as GameObject).transform;
		}

		
		// Save camera offset so we can use it in the first frame
		cameraOffset = mainCameraTransform.position - character.position;
		
		// Set the initial cursor position to the center of the screen
		cursorScreenPosition = new Vector3 (0.5f * Screen.width, 0.5f * Screen.height, 0);
		
		// caching movement plane
		playerMovementPlane = new Plane (character.up, character.position + character.up * cursorPlaneHeight);
	}
	
	void Start() {
		screenMovementSpace = Quaternion.Euler (0, mainCameraTransform.eulerAngles.y, 0);
		screenMovementForward = screenMovementSpace * Vector3.forward;
		screenMovementRight = screenMovementSpace * Vector3.right;	
	}
	
	void Update() {
		// HANDLE CHARACTER MOVEMENT DIRECTION
		move.movementDirection = Input.GetAxis ("Horizontal") * screenMovementRight + Input.GetAxis ("Vertical") * screenMovementForward;

		// Make sure the direction vector doesn't exceed a length of 1
		// so the character can't move faster diagonally than horizontally or vertically
		if (move.movementDirection.sqrMagnitude > 1)
			move.movementDirection.Normalize();
		
		
		// HANDLE CHARACTER FACING DIRECTION AND SCREEN FOCUS POINT
		
		// First update the camera position to take into account how much the character moved since last frame
		
		// Set up the movement plane of the character, so screenpositions
		// can be converted into world positions on this plane
		
		// optimization (instead of newing Plane):
		
		playerMovementPlane.normal = character.up;
		playerMovementPlane.distance = -character.position.y + cursorPlaneHeight;
		
		// used to adjust the camera based on cursor or joystick position
		
		Vector3 cameraAdjustmentVector = Vector3.zero;
		
		
		// On PC, the cursor point is the mouse position
		Vector3 cursorScreenPosition = Input.mousePosition;
					
		// Find out where the mouse ray intersects with the movement plane of the player
		Vector3 cursorWorldPosition = ScreenPointToWorldPointOnPlane (cursorScreenPosition, playerMovementPlane, mainCamera);
		
		float halfWidth = Screen.width / 2.0f;
		float halfHeight = Screen.height / 2.0f;
		float maxHalf = Mathf.Max (halfWidth, halfHeight);
		
		// Acquire the relative screen position			
		Vector3 posRel = cursorScreenPosition - (new Vector3 (halfWidth, halfHeight, cursorScreenPosition.z));		
		posRel.x /= maxHalf; 
		posRel.y /= maxHalf;
					
		cameraAdjustmentVector = posRel.x * screenMovementRight + posRel.y * screenMovementForward;
		cameraAdjustmentVector.y = 0.0f;	
								
		// The facing direction is the direction from the character to the cursor world position
		move.facingDirection = (cursorWorldPosition - character.position);
		move.facingDirection.y = 0;			
				
			
		// HANDLE CAMERA POSITION
			
		// Set the target position of the camera to point at the focus point
		Vector3 cameraTargetPosition = character.position + initOffsetToPlayer + cameraAdjustmentVector * cameraPreview;
		
		// Apply some smoothing to the camera movement
		mainCameraTransform.position = cameraTargetPosition;
		
		// Save camera offset so we can use it in the next frame
		cameraOffset = mainCameraTransform.position - character.position;
	}
	
	public static Vector3 PlaneRayIntersection (Plane plane, Ray ray) {
		float dist;
		plane.Raycast (ray, out dist);
		return ray.GetPoint (dist);
	}

	public static Vector3 ScreenPointToWorldPointOnPlane (Vector3 screenPoint, Plane plane, Camera camera) {
		// Set up a ray corresponding to the screen position
		Ray ray = camera.ScreenPointToRay (screenPoint);
		
		// Find out where the ray intersects with the plane
		return PlaneRayIntersection (plane, ray);
	}
	


}